/*******************************************************************************
 * Copyright (c) 2012 Clever Devices.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/gpl.html
 * 
 * Contributors:
 * 	Clever Devices Interns - 
 * 	Alex Frankel, Andria Young, Kevin Thomas, Nicholas Culpepper, Taner Oztimurlenk, Thomas Volberg
 ******************************************************************************/
package com.framework.bustime_parser;

import java.util.ArrayList;
import java.util.List;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import android.os.AsyncTask;

import com.framework.beans.Bus;
import com.framework.beans.Prediction;
import com.framework.beans.Route;
import com.framework.beans.Stop;
import com.google.android.maps.GeoPoint;


/**
 * Class used to retrieve and parse the XML from the BusTime API
 * All necessary API calls (urls) are stored here as strings
 * 
 * @author AFrankel
 *
 */
public class ApiHandler{
	
	public ApiHandler(){}
	
	/**
	 * return the xml string for the given url
	 * 
	 * @param url any specifiers (i.e. rt=49) need to be contained in
	 * THIS url string
	 * @return xml string
	 */
	public String getXML(String url){			
		XMLParser parser = new XMLParser();
		String xml = parser.getXmlFromUrl(url);
		return xml;
	}
	
	/**
	 * returns the list of buses for a specific route for the given
	 * xml
	 * 
	 * @param xml 
	 * @return
	 */
	public ArrayList<Bus> getBusesForRoute(String xml){
		
		parser = new XMLParser();
		ArrayList<Bus> busList = new ArrayList<Bus>();
		
		doc = parser.getDomElement(xml);
		
		nl = doc.getElementsByTagName(KEY_BUS);
		
		for(int i = 0;i<nl.getLength();i++){
			//an element is one instance of a <bus>
			Element e = (Element) nl.item(i);
			
			double tempLat = Double.parseDouble(parser.getValue(e, KEY_LAT));
			double tempLon = Double.parseDouble(parser.getValue(e, KEY_LON));
			
			//convert from BusTime geolocation to android geopoint  
			int lat = (int)(tempLat*1000000);
			int lon = (int)(tempLon*1000000);
			
			int id = Integer.parseInt(parser.getValue(e, KEY_ID));
			String dest = parser.getValue(e, KEY_DEST);
			
			Bus bus = new Bus(lat,lon,id,dest);
			busList.add(bus);
		}
		return busList;
	}
	
	/**
	 * returns all route for the entire CTA
	 * 
	 * @param xml
	 * @return
	 */
	public ArrayList<Route> getRoutes(String xml){
		ArrayList<Route> routes = new ArrayList<Route>();
		parser = new XMLParser();
		
		System.out.println(xml);
		
		doc = parser.getDomElement(xml);
		
		nl = doc.getElementsByTagName(KEY_ROUTE);
		System.out.println(xml);
		
		for(int i = 0; i<nl.getLength();i++){
			e = (Element)nl.item(i); 
			
			String des = parser.getValue(e, KEY_ROUTE_NAME);
			String id = parser.getValue(e, KEY_ROUTE_ID);
			
			routes.add(new Route(des,id));
		}
		
		return routes;
	}
	
	/**
	 * returns predictions for a given stop
	 * @param xml
	 * @return
	 */
	public ArrayList<Prediction> getPredicitons(String xml){
		ArrayList<Prediction> predictions = new ArrayList<Prediction>();
		parser = new XMLParser();
		doc = parser.getDomElement(xml);
		
		System.out.println(xml);
		
		nl = doc.getElementsByTagName(KEY_PREDICTION);
		
		for(int i = 0; i<nl.getLength(); i++){
			e = (Element)nl.item(i);
			
			String stop = parser.getValue(e, KEY_STOP_NM);
			String vid = parser.getValue(e, KEY_ID);
			String rt = parser.getValue(e, KEY_ROUTE_ID);
			String des = parser.getValue(e, KEY_DEST);
			String time = parser.getValue(e, KEY_TIME);
			String prd = parser.getValue(e, KEY_PREDICTION_TIME);
			
			predictions.add(new Prediction(stop,vid,rt,des,time,prd));
			
		}
		return predictions;
	}
	
	/**
	 * Unused.  Original intention was to display the next stop for a bus,
	 * so that if tapped on the map that is what would be displayed.  Ended up being very
	 * slow so I scrapped it
	 * 
	 * @param xml
	 * @return
	 */
	public Prediction getNextStop(String xml){

		parser = new XMLParser();
		doc = parser.getDomElement(xml);
		
		nl = doc.getElementsByTagName(KEY_PREDICTION);

		e = (Element) nl.item(0);

		String stop = parser.getValue(e, KEY_STOP_NM);
		String vid = parser.getValue(e, KEY_ID);
		String rt = parser.getValue(e, KEY_ROUTE_ID);
		String des = parser.getValue(e, KEY_DEST);
		String time = parser.getValue(e, KEY_TIME);
		String prd = parser.getValue(e, KEY_PREDICTION_TIME);
		
		return new Prediction(stop,vid,rt,des,time,prd);

	}
	
	/**
	 * returns directions for a route (i.e. East Bound, West Bound).  Had trouble
	 * parsing this xml data due to its layout and as a result could only get the first
	 * of two directions.
	 * 
	 * @param xml
	 * @return
	 */
	public ArrayList<String> getDirectionsForRoute(String xml){
		ArrayList<String> directions = new ArrayList<String>();
		
		parser = new XMLParser();
		doc = parser.getDomElement(xml);
		
		nl = doc.getElementsByTagName(KEY_RESPONSE);
		
		e = (Element) nl.item(0);
		
		System.out.println(xml);
		
		//assuming there are only two directions for each route...
		String dir = parser.getValue(e, KEY_DIRECTION);
		System.out.println("DIRECTION: " + dir);
		directions.add(dir);
		
		dir = parser.getValue(e, KEY_DIRECTION);
		System.out.println("DIRECTION: " + dir);
		directions.add(dir);
		
		return directions;
	}
	
	/**
	 * returns pattern of GeoPoints to draw a route on the map
	 * 
	 * @param xml
	 * @return
	 */
	public ArrayList<GeoPoint> getPatterns(String xml){
		ArrayList<GeoPoint> points = new ArrayList<GeoPoint>();
		
		parser = new XMLParser();
		doc = parser.getDomElement(xml);
		
		nl = doc.getElementsByTagName(KEY_POINT);
		
		for(int i = 0; i<nl.getLength(); i++){
			e = (Element)nl.item(i);
			
			double tempLat = Double.parseDouble(parser.getValue(e, KEY_LAT));
			double tempLon = Double.parseDouble(parser.getValue(e, KEY_LON));
			int lat = (int)(tempLat*1000000);
			int lon = (int)(tempLon*1000000);
			
			points.add(new GeoPoint(lat,lon));
			
		}
		
		return points;
	}
	
	
	 /**
	  * Gets all the stops for a given route, used with ArrivalsGrid
	  * 
	  * @param xml
	  * @return
	  */
	public ArrayList<Stop> getStops(String xml){
		ArrayList<Stop> stops = new ArrayList<Stop>();
		parser = new XMLParser();
		doc = parser.getDomElement(xml);
		
		nl = doc.getElementsByTagName(KEY_STOP);
		
		for(int i = 0; i<nl.getLength(); i++){
			e = (Element) nl.item(i);
			
			String stopId = parser.getValue(e, KEY_STOP_ID);
			String stopName = parser.getValue(e, KEY_STOP_NM);
			
			double tempLat = Double.parseDouble(parser.getValue(e, KEY_LAT));
			double tempLon = Double.parseDouble(parser.getValue(e, KEY_LON));
			int lat = (int)(tempLat*1000000);
			int lon = (int)(tempLon*1000000);
			
			stops.add(new Stop(stopId,stopName, lat, lon));
		}
		
		return stops;
	}
	
	
	
	/**
	 * Ended up not using this, but probably makes sense to for simplicity's sake
	 * 
	 * @param method designator for api call (i.e. getRoute)
	 * @param ending optional specifier for certain call, if blank just enter ""
	 * @return url for api call
	 */
	public static String constructString(String method,String ending){
		return BEGINNING + method + KEY + ending;
	}
	
	/**
	 * adds the proper suffix for finding direction in the api.  UNUSED
	 * 
	 * @param direction to modify
	 * @return suffix for API http call
	 */
	public static String addDirection(String direction){
		String edDirection = "&dir=";
		String [] temp = direction.split(" ");
		edDirection+=temp[0]+"%20"+temp[1];
		System.out.println(edDirection);
		
		return edDirection;
	}
	
	//for retrieving DOM elements
	static final String KEY_BUS = "vehicle";
	static final String KEY_ROUTE_NAME = "rtnm";
	static final String KEY_ROUTE = "route"; // for use with getRoutes?
	static final String KEY_ROUTE_ID = "rt";
	static final String KEY_ID = "vid";
	static final String KEY_LAT = "lat";
	static final String KEY_LON = "lon";
	static final String KEY_DEST = "des";
	static final String KEY_STOP_ID = "stpid";
	static final String KEY_STOP_NM = "stpnm";
	static final String KEY_TIME = "tmstmp";
	static final String KEY_PREDICTION_TIME = "prdtm";
	static final String KEY_PREDICTION = "prd";
	static final String KEY_POINT = "pt";
	static final String KEY_RESPONSE = "bustime-response";
	static final String KEY_DIRECTION = "dir";
	static final String KEY_STOP = "stop";
	
	public static final String BUSES_FOR_ROUTE_URL = "http://cta.cleverdevices.com:8100/bustime/api/v1/getvehicles?key=hjby6THk78nvR9XE7ng97xnXx&rt=";
	public static final String GET_ROUTES = "http://cta.cleverdevices.com:8100/bustime/api/v1/getroutes?key=hjby6THk78nvR9XE7ng97xnXx";
	public static final String GET_PREDICTIONS = "http://cta.cleverdevices.com:8100/bustime/api/v1/getpredictions?key=hjby6THk78nvR9XE7ng97xnXx&";
	public static final String GET_PATTERNS = "http://cta.cleverdevices.com:8100/bustime/api/v1/getpatterns?key=hjby6THk78nvR9XE7ng97xnXx&rt=";
	public static final String GET_DIRECTIONS = "http://cta.cleverdevices.com:8100/bustime/api/v1/getdirections?key=hjby6THk78nvR9XE7ng97xnXx&rt=";
	public static final String BEGINNING = "http://cta.cleverdevices.com:8100/bustime/api/v1/";
	public static final String GET_STOPS = "http://cta.cleverdevices.com:8100/bustime/api/v1/getstops?key=hjby6THk78nvR9XE7ng97xnXx&rt=";
	public static final String KEY = "key=hjby6THk78nvR9XE7ng97xnXx";
	//format for call should be BEGINNING + <methodcall?> + KEY + <designators>
	
	NodeList nl;
	Document doc;
	XMLParser parser;
	Element e;
	
}	
